## Selecionar membros da amostra: Sorteia unidades da população suficientes para a quota proporcional de acordo com o gênero sexual
## Copyright (c) 2018 Adonay Felipe Nogueira <https://libreplanet.org/wiki/User:Adfeno>

## This program is free software: you can redistribute it and/or
## modify it under the terms of the GNU General Public License as
## published by the Free Software Foundation, version 3 of the
## License.

## This program is distributed in the hope that it will be useful, but
## WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
## General Public License for more details.

## You should have received a copy of the GNU General Public License
## along with this program.  If not, see
## <https://www.gnu.org/licenses/>.

## Lê os caminhos dos arquivos de entrada e saída.
args <- commandArgs(trailingOnly = TRUE)
arquivo_de_entrada_csv <- args[1]
arquivo_de_saida_csv <- args[2]

## Lê o arquivo de entrada. `check.names = FALSE' faz os nomes das
## colunas serem importados com espaços, `na.strings = ""' faz com que
## as células vazias sejam realmente consideradas como valores em falta
## pelo interpretador GNU R.
academicos <- read.csv(arquivo_de_entrada_csv,
                       check.names = FALSE,
                       na.strings = "")

## Não queremos selecionar um membro da população que fora impedido,
## mas ao mesmo tempo não queremos selecionar uma amostra maior do que
## a quota que precisamos. `is.na' retorna resultado verdadeiro (TRUE)
## se a célula avaliada possuir valor faltante, esta verificação é
## necessária pois do contrário, qualquer outra tentativa de conseguir
## subconjuntos resultaria em um comportamento no qual estas células
## seriam descartadas ou todas as outras seriam apresentadas com
## valores faltantes; `==' retorna verdadeiro (TRUE) caso os objetos da
## esquerda e da direita sejam iguais;`!=' espera pelo inverso; `|' e
## `&' são "ou" e "e" lógicos, respectivamente; parêntesis são
## agrupadores; `!' inverte o resultado lógico de uma operação.
filtro_para_excluir_impedidos <-
    paste('is.na(academicos$"Situação na pesquisa") ',
          '| (academicos$"Situação na pesquisa" != "Selecionado" ',
          '& academicos$"Situação na pesquisa" != "Ausente" ',
          '& academicos$"Situação na pesquisa" != "Recusou" ',
          '& academicos$"Situação na pesquisa" != "Participou")',
          sep = "")
filtro_para_contar_participantes <-
    paste('! is.na(academicos$"Situação na pesquisa") ',
          '& (academicos$"Situação na pesquisa" == "Selecionado" ',
          '| academicos$"Situação na pesquisa" == "Participou")',
          sep="")

## `ceiling()' calcula o teto de um número real; `unique()' retorna os
## valores removendo suas duplicatas; `length()' retorna o número
## total de itens em uma lista.
quota_proporcional.F <-
    ceiling(length(unique(academicos[academicos$"Gênero sexual" == "F",
                                     "Nome"])) *
            (length(unique(academicos[academicos$"Gênero sexual" == "F",
                                      "Nome"])) /
             length(unique(academicos[,
                                      "Nome"]))))
quota_proporcional.M <-
    ceiling(length(unique(academicos[academicos$"Gênero sexual" == "M",
                                     "Nome"])) *
            (length(unique(academicos[academicos$"Gênero sexual" == "M",
                                      "Nome"])) /
             length(unique(academicos[,
                                      "Nome"]))))

## `factor()' remove os níveis/valores que eram possíveis antes da
## criação do subconjunto, mas que não são mais presentes no novo
## conjunto; `(eval(parse(text=...)))' converte uma cadeia de
## caracteres em parâmetros ou objetos para o GNU R e seus comandos.
nomes_disponiveis.F <-
    factor(unique(academicos[academicos$"Gênero sexual" == "F"
                             & (eval(parse(text=filtro_para_excluir_impedidos))),
                             "Nome"]))
nomes_disponiveis.M <-
    factor(unique(academicos[academicos$"Gênero sexual" == "M"
                             & (eval(parse(text=filtro_para_excluir_impedidos))),
                             "Nome"]))

quantidade_faltando.F <-
    quota_proporcional.F -
    length(unique(academicos[academicos$"Gênero sexual" == "F"
                             & (eval(parse(text=filtro_para_contar_participantes))),
                             "Nome"]))
quantidade_faltando.M <-
    quota_proporcional.M -
    length(unique(academicos[academicos$"Gênero sexual" == "M"
                             & (eval(parse(text=filtro_para_contar_participantes))),
                             "Nome"]))

## `sample()' retira amostras de uma população, o que por padrão no
## GNU R é feito de forma que os membros já selecionados sejam
## retirados da probabilidade dos demais sorteios; `length()' retorna
## o total de itens em uma lista; `if() {} else {}' faz uma
## comparação, e caso seja verdade, usa o conteúdo do primeiro par de
## chaves, se não: usa o segundo; `<=' compara numericamente se o lado
## esquerdo é menor ou igual ao direito. Essa combinação entre `if()
## {} else {}', `<=' e as demais variáveis é necessário pois quando
## `sample()' opera retirando os já selecionados das probabilidades
## subsequentes, esta função não pode receber um número de
## vagas/requerimentos maior que a "população" informada.
nomes_selecionados.F <-
    sample(nomes_disponiveis.F,
           if(quantidade_faltando.F <= length(nomes_disponiveis.F)) {
               quantidade_faltando.F}
           else {
               length(nomes_disponiveis.F)})

nomes_selecionados.M <-
    sample(nomes_disponiveis.M,
           if(quantidade_faltando.M <= length(nomes_disponiveis.M)) {
               quantidade_faltando.M}
           else {
               length(nomes_disponiveis.M)})

## Para todos os membros da população que foram sorteados, insere-se
## na célula da coluna "Situação na pesquisa" o status de
## "Selecionado". Ao invés de calcular os índices em partes anteriores
## deste script, usa-se `%in%' para comparar cada célula da coluna
## "Nome" com as listas de nomes selecionados, de modo que um nome em
## várias linhas também seja selecionado.
academicos[academicos$"Nome" %in%
           nomes_selecionados.F
           | academicos$"Nome" %in%
             nomes_selecionados.M,
           "Situação na pesquisa"] <- "Selecionado"

## Escreve o resultado no arquivo de saída. `na = ""' faz as células
## com valores faltantes serem exportadas com campo vazio; `row.names
## = FALSE' exclui a coluna que contém o nome das linhas.
write.csv(academicos, file = arquivo_de_saida_csv, na = "", row.names = FALSE)
